#include <stdio.h>
#include <opencv2/imgproc.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <string.h>
#include "cgic.h"
#include <opencv2/opencv.hpp>

//#define WIDTH 1920
//#define HEIGHT 1080

#define WIDTH 640
#define HEIGHT 480

union semun {
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};

#define YUV_FRAME_SIZE WIDTH * HEIGHT  * 3 / 2
#define RGB_FRAME_SIZE WIDTH * HEIGHT  * 3 


int semid;
struct sembuf sem_p;
struct sembuf sem_v;


int main()
// int cgiMain()
{
    // 输出Content-type 头部
    printf("HTTP/1.0 200 OK\r\n");
    printf("Server: Motion/4.1.1\r\n");
    printf("Connection: close\r\ncd ");
    printf("Max-Age: 0\r\n");
    printf("Expires: 0\r\n");
    printf("Cache-Control: no-cache, private\r\n");
    printf("Pragma: no-cache\r\n");
    printf("Content-Type: multipart/x-mixed-replace; boundary=Hello_Harry\r\n\r\n");
    // printf("Content-Type: multipart/x-mixed-replace; boundary=Hello_Harry\n\n");

    //信号量的初始化
    key_t sem_key = ftok("/etc/semfile", 65); // 生成IPC键值
    semid = semget(sem_key, 1, 0666|IPC_CREAT); // 创建信号量集合，只有一个信号量
    union semun sem_union;
    sem_union.val = 1; // 初始化信号量为1
    semctl(semid, 0, SETVAL, sem_union); // 设置信号量默认值

    sem_p = {0, -1, 0};
    sem_v = {0, 1, 0};

    //共享内存的初始化
    int shmid;
    char *shmaddr;
    const char *pathname = "/etc/video_share_vdec";
    int proj_id = 65;
    key_t key = ftok(pathname, proj_id);

    // 创建共享内存段
    shmid = shmget(key, YUV_FRAME_SIZE, 0666);
    if (shmid == -1)
    {
        perror("shmget failed");
        exit(EXIT_FAILURE);
    }

    shmaddr = (char *)shmat(shmid, 0, 0); //对共享内存进行映射
    if (shmaddr == (void *)-1)
    {
        perror("shmat failed");
        exit(EXIT_FAILURE);
    }

#if 1
    cv::Mat yuvImg;
    yuvImg.create(HEIGHT * 3 / 2 , WIDTH, CV_8UC1); //图像格式为YUV420,nv12
    int bufLen = YUV_FRAME_SIZE;
    while (true) 
    {
        semop(semid, &sem_p, 1);
        memcpy(yuvImg.data, shmaddr, bufLen * sizeof(unsigned char)); //VDEC数据拷贝到OPENCV矩阵
        semop(semid, &sem_v, 1);
        
        cv::Mat rgbImg;
        cv::cvtColor(yuvImg, rgbImg, cv::COLOR_YUV2RGB_YV12); //把NV12数据转换成RGB彩色图像
        std::vector<uchar> buf;
        cv::imencode(".jpg", rgbImg, buf); //图片数据转换成jpg字节流
        std::cout << "--Hello_Harry\r\nContent-type: image/jpeg\r\n\r\n";
        std::cout.write(reinterpret_cast<const char *>(buf.data()), buf.size()); //把字节流的数据刷新到HTTP服务器
        std::cout.flush(); // 刷新输出缓冲区
    }
#endif


#if 0
    cv::Mat rgbImg;
    rgbImg.create(HEIGHT , WIDTH, CV_8UC3);
    while (true)
    {
        memcpy(rgbImg.data, shmaddr, RGB_FRAME_SIZE);
        std::vector<uchar> buf;
        cv::imencode(".jpg", rgbImg, buf);
        std::cout << "--Hello_Harry\r\nContent-type: image/jpeg\r\n\r\n";
        std::cout.write(reinterpret_cast<const char *>(buf.data()), buf.size());
        std::cout.flush(); // 刷新输出缓冲区
    }
#endif
    if (shmdt(shmaddr) == -1)
    {
        perror("shmdt failed");
        exit(EXIT_FAILURE);
    }

    // 删除共享内存段
    if (shmctl(shmid, IPC_RMID, 0) == -1)
    {
        perror("shmctl failed");
        exit(EXIT_FAILURE);
    }

    return 0;
}
